home *** CD-ROM | disk | FTP | other *** search
/ Precision Software Appli…tions Silver Collection 1 / Precision Software Applications Silver Collection Volume One (PSM) (1993).iso / tutor / asm1tut.exe / CHAP11-2.DOC < prev    next >
Text File  |  1990-06-25  |  20KB  |  507 lines

  1.  
  2.  
  3.  
  4.              The PC Assembler Tutor                                        114
  5.              ______________________
  6.  
  7.              We can consolidate all this information into the following list:
  8.  
  9.                  All the following addressing modes can be used with or
  10.                  without a constant:
  11.  
  12.                  variable_name  (+constant)
  13.                  [bx]     (+constant)
  14.                  [si]     (+constant)
  15.                  [di]     (+constant)
  16.                  [bp]     (+constant)
  17.                  [bx+si]  (+constant)
  18.                  [bx+di]  (+constant)
  19.                  [bp+si]  (+constant)
  20.                  [bp+di]  (+constant)
  21.  
  22.                  This is a complete list.
  23.  
  24.              Thus, you can access a variable by name or with one of the eight
  25.              pointer combinations. There are no other possibilities.
  26.  
  27.  
  28.              One thing that may confuse you about an addressing statement is
  29.              all the plusses and minuses. As an example:
  30.  
  31.                  mov  cx, -45+27[bx+22]+[-195+di]+23-44
  32.  
  33.              the total address is:
  34.  
  35.                  -45+27[bx+22]+[-195+di]+23-44
  36.  
  37.              When the 8086 performs this instruction, it will ADD (1) BX (2)
  38.              DI and (3) a single constant. That single constant can be a
  39.              positive or a negative number; the 8086 will ADD all three
  40.              elements. The '+' in front of  'di' is for convenience of the
  41.              assembler only;  [-195-di] is illegal and the assembler will
  42.              generate an error. If you actually want the negative of what is
  43.              in one of the registers, you must negate it before calling the
  44.              addressing instruction:
  45.  
  46.                  neg  di
  47.                  mov  cx, -45+27[bx+22]+[-195+di]+23-44
  48.  
  49.              once again, the only allowable forms are +[di], [di] or [+di].
  50.              Either -[di] or [-di] will generate an assembler error. 
  51.  
  52.  
  53.              If you ever see a technical description of the addressing modes,
  54.              you will find a list of 24 different machine codes. The reason
  55.              for this is that:
  56.  
  57.                       [bx]
  58.                       [bx] + byte constant
  59.                       [bx] + word constant
  60.  
  61.              are three different machine codes. Here is a listing of the same
  62.              machine instruction with the three different styles:
  63.  
  64.  
  65.  
  66.  
  67.  
  68.              Chapter 11 - Addressing Modes                                 115
  69.              _____________________________
  70.  
  71.  
  72.                  MACHINE CODE             ASSEMBLER INSTRUCTION
  73.  
  74.                   03 04                     add   ax, [si] 
  75.                   03 44 1B                  add   ax, [si+27] 
  76.                   03 44 E5                  add   ax, [si-27] 
  77.                   03 84 5BA7                add   ax, [si+23463] 
  78.                   03 84 A459                add   ax, [si-23463] 
  79.  
  80.  
  81.              (27d = 1Bh , 23463d = 5BA7h). The first byte of code (03) is the
  82.              add (word) instruction. The second byte is the addressing code,
  83.              and the third and fourth bytes (if any) are the constant (in
  84.              hex). Addressing code 04 is:  (ax, [si]). Addressing code 44 is: 
  85.              (ax, [si] + byte constant). Addressing code 84 is:  (ax, [si] +
  86.              word constant). The fact that there are three different machine
  87.              codes is of concern to the assembler, not to you. It is the
  88.              assembler's job to make the machine code as efficient as
  89.              possible. It is your job to write quality, robust code.
  90.  
  91.  
  92.              SEGMENT OVERRIDES
  93.  
  94.              So far, we haven't talked about segment registers. You will
  95.              remember from the last chapter that the 8086 assumes that a named
  96.              variable is in the DS segment:
  97.  
  98.                  mov  ax, variable1
  99.  
  100.              If it isn't, the Microsoft assembler puts the correct segment
  101.              override in the machine code. The segment overrides are:
  102.  
  103.                  SEGMENT OVERRIDE         MACHINE CODE (hex)
  104.                       CS                       2E
  105.                       DS                       3E
  106.                       ES                       26
  107.                       SS                       36
  108.  
  109.              As an example:
  110.  
  111.                  MACHINE CODE        ASSEMBLER  INSTRUCTIONS
  112.  
  113.                  2E: 03 06 0000 R      add   ax, variable3 
  114.                  26: 2B 1E 0000 R      sub   bx, variable2 
  115.                  31 36 0000 R          xor   variable1, si ; no override
  116.                  36: 21 3E 00C8 R      and   variable4, di 
  117.  
  118.              when the different variables were in segments with different
  119.              ASSUME statements. If you don't remember this, you should reread
  120.              the section on overrides in the last chapter. Remember, the colon
  121.              is in the listing only to tell you that we have a segment
  122.              override. The colon is not in the machine code.
  123.  
  124.  
  125.  
  126.  
  127.  
  128.  
  129.  
  130.  
  131.  
  132.              The PC Assembler Tutor                                        116
  133.              ______________________
  134.  
  135.              What about pointers? The natural segment for anything with [bp]
  136.              is SS, the stack segment.{1}  Everything else has DS as its
  137.              natural segment. The natural segments are:
  138.  
  139.                  (1) DS
  140.  
  141.                       variable + (constant)
  142.                       [bx] + (constant)
  143.                       [si] + (constant)
  144.                       [di] + (constant)
  145.                       [bx+si] + (constant)
  146.                       [bx+di] + (constant)
  147.  
  148.  
  149.                  (2) SS
  150.  
  151.                       [bp] + (constant)
  152.                       [bp+si] + (constant)
  153.                       [bp+di] + (constant)
  154.  
  155.              where the constant is always optional. Can you use segment
  156.              overrides? Yes, in all cases.{2}  Here is some assembler code
  157.              along with the machine code which was generated.
  158.  
  159.  
  160.                  MACHINE CODE             ASSEMBLER INSTRUCTIONS
  161.                                       
  162.                   26: 03 07                 add   ax, es:[bx] 
  163.                   2E: 01 05                 add   cs:[di], ax 
  164.                   36: 2B 44 11              sub   ax, ss:[si+17] 
  165.                   2E: 29 46 00              sub   cs:[bp], ax 
  166.                   3E: 33 03                 xor   ax, ds:[bp+di] 
  167.                   26: 31 02                 xor   es:[bp+si], ax 
  168.                   26: 89 43 16              mov   es:[bp+di+22], ax 
  169.               
  170.               
  171.                   03 04                     add   ax, [si] 
  172.                   03 44 1B                  add   ax, [si+27] 
  173.                   03 84 A459                add   ax, [si-23463] 
  174.                   26: 03 04                 add   ax, es:[si] 
  175.                   26: 03 44 1B              add   ax, es:[si+27] 
  176.                   26: 03 84 A459            add   ax, es:[si-23463] 
  177.  
  178.  
  179.              (17d = 11h, 22d = 16h, 27d = 1Bh, -23463d = 0A459h). The first
  180.              number (which is followed by a colon) is the segment override
  181.              that the assembler has inserted in the machine code. Remember,
  182.              the colon is in the listing to inform you that an override is
  183.              ____________________
  184.  
  185.                 1 We will see why when we look at subroutines. BP is called
  186.              the base pointer [bp] and is used in a special way.
  187.  
  188.                 2 There are some special instructions for two independent
  189.              pointers which we will cover at the end of the book. These allow
  190.              segment overrides but force the override to refer to the first
  191.              pointer.
  192.  
  193.  
  194.  
  195.  
  196.              Chapter 11 - Addressing Modes                                 117
  197.              _____________________________
  198.  
  199.              involved; it is not in the machine code itself.
  200.                                        
  201.              Unfortunately, when you use pointers you must put the override
  202.              into the assembler instructions yourself. The assembler has no
  203.              way of knowing that you want an override. This can cause some
  204.              truly gigantic errors (if you reference a pointer seven times and
  205.              forget the override once, the 8086 will access the wrong segment
  206.              that one time), and those errors are extremely difficult to
  207.              detect.
  208.  
  209.              As you can see from above, you put the override in the
  210.              instructions by writing the appropriate segment (CS, DS, ES or
  211.              SS) followed by a colon. As always, it is your responsibility to
  212.              make sure that the segment register holds the address of the
  213.              appropriate segment before using an override. 
  214.  
  215.  
  216.              We have talked about two different types of constants in the
  217.              chapter, a constant which is part of the address:
  218.  
  219.                  mov  ax, [bx+17]
  220.                  add  [si+2190], dx
  221.                  and  [di-8179], cx
  222.  
  223.              and a constant which is a number to used for an arithmetical or
  224.              logical operation:
  225.  
  226.                  add  ax, 17
  227.                  sub  dl, 45
  228.                  add  dx, 22187
  229.  
  230.              They are both part of the machine instruction, and are
  231.              unchangeable (true constants). This machine code is going to be
  232.              difficult to read, so just look for (1) the constant DATA and (2)
  233.              the constant in the ADDRESS. All constants in the assembler
  234.              instructions are in hex so that they look the same as in the
  235.              listing of the machine code. Here's a listing of different
  236.              combinations.
  237.  
  238.  
  239.              1. Pointer + constant as an address:
  240.  
  241.                  MACHINE CODE             ASSEMBLER INSTRUCTIONS
  242.                   01 44 1B                  add   [si+1Bh], ax 
  243.                   29 85 0A04                sub   [di+0A04h], ax 
  244.                   30 5C 1F                  xor   [si+1Fh], bl 
  245.                   20 9E 1FAB                and   [bp+1FABh], bl 
  246.               
  247.              2. Arithmetic instruction with a constant:
  248.  
  249.                  MACHINE CODE             ASSEMBLER INSTRUCTIONS
  250.                   05 1065                   add   ax, 1065h 
  251.                   2D 6771                   sub   ax, 6771h 
  252.                   80 F3 37                  xor   bl, 37h 
  253.                   80 E3 82                  and   bl, 82h 
  254.               
  255.              3. Pointer + constant as an address; arithmetic with a constant
  256.  
  257.  
  258.  
  259.  
  260.              The PC Assembler Tutor                                        118
  261.              ______________________
  262.  
  263.  
  264.                  MACHINE CODE             ASSEMBLER INSTRUCTIONS
  265.                   81 44 1B 1065             add   [si+1Bh], 1065h 
  266.                   81 AD 0A04 6771           sub   [di+0A04h], 6771h 
  267.                   80 74 1F 37               xor   [si+1Fh], BYTE PTR 37h 
  268.                   80 A6 1FAB 82             and   [bp+1FABh], BYTE PTR 82h 
  269.               
  270.  
  271.              You will notice that the ADD instruction (as well as the other
  272.              instructions) changes machine code depending on the complete
  273.              format of the instruction (byte or word? to a register or from a
  274.              register? what addressing mode? is AX one of the registers?).
  275.              That's part of the 8086 machine language encoding, and it makes
  276.              the 8086 machine code extremely difficult to decipher without a
  277.              table listing all the options.
  278.  
  279.  
  280.              OFFSET AND SEG
  281.  
  282.              There are two special instructions that the assembler has -
  283.              offset and seg. For any variable or label, offset gives the
  284.              offset from the beginning of the segment, and seg gives the
  285.              segment address. If you write:
  286.  
  287.                  mov  ax, offset variable1
  288.  
  289.              the assembler will calculate the offset of variable1 and put it
  290.              in the machine code. It also signals the linker and loader; if
  291.              the linker should change the offset during linking, it will also
  292.              adjust this number. If you write:
  293.  
  294.                  mov  dx, seg variable1
  295.  
  296.              The assembler will signal to the linker and the loader that you
  297.              want the address of the segment that variable1 is in. The linker
  298.              and loader will put it in the machine code at that spot. You
  299.              don't need to know the name of the segment. The linker takes care
  300.              of that. We will use the seg operator later. 
  301.  
  302.  
  303.              LEA
  304.  
  305.              LEA (load effective address) is a completely different animal. It
  306.              allows you to use any addressing mode to put an address in a
  307.              register. One of the addressing modes covered before was for the
  308.              following code:
  309.  
  310.                            xor  dx, 45+[di+23][bx+15]-94
  311.  
  312.              The 8086 added DI, BX and the constant to calculate the address.
  313.              It then XOR'ed the variable at that address with DX. If you
  314.              write:
  315.  
  316.                            lea  dx, 45+[di+23][bx+15]-94
  317.  
  318.              the 8086 will add DI, BX and the constant to calculate the
  319.              address. It will then put the ADDRESS in DX. LEA can use any
  320.  
  321.  
  322.  
  323.  
  324.              Chapter 11 - Addressing Modes                                 119
  325.              _____________________________
  326.  
  327.              addressing mode to calculate an address. The machine code looks
  328.              almost the same:
  329.  
  330.                  MACHINE CODE                  ASSEMBLER INSTRUCTIONS
  331.  
  332.                   33 51 F5                  xor dx, 45+[di+23][bx+15]-94 
  333.                   8D 51 F5                  lea dx, 45+[di+23][bx+15]-94 
  334.  
  335.              The first byte of the machine code is the instruction and the
  336.              second and third byte are the addressing mode.
  337.  
  338.              You almost never need LEA. It is slower than:
  339.  
  340.                  mov  dx, offset variable1
  341.  
  342.              However, when the addressing gets complicated (perhaps 1% of the
  343.              time), it's nice to have. Remember, it will calculate ANY 8086
  344.              addressing mode.
  345.  
  346.              Let's run a program so we can see what actually happens with LEA
  347.  
  348.              ;lea.asm
  349.              ; + + + + + + + + + + + + + + + START DATA BELOW THIS LINE 
  350.              variable1 dw ? 
  351.              ; + + + + + + + + + + + + + + + END DATA ABOVE THIS LINE 
  352.  
  353.              ; + + + + START CODE BELOW THIS LINE 
  354.                     ; reg style 
  355.                     mov   si_byte, 1   ; signed 
  356.                     lea   ax, ax_byte 
  357.                     call  set_reg_style 
  358.               
  359.                     mov   bp, 0  ; clear unused registers  
  360.                     mov   di, 0 
  361.                  
  362.                    ;lea and mov show the two ways to address variable1
  363.                     lea   ax, variable1  ; effective address 
  364.                     mov   bx, offset variable1  ; offset 
  365.                     call  show_regs_and_wait 
  366.               
  367.              lea_loop: 
  368.                     mov   si, 0  ; clear registers 
  369.                     mov   dx, 0 
  370.                     mov   cx, 0 
  371.                     mov   bx, 0 
  372.                     mov   ax, 0 
  373.                     call  show_regs 
  374.               
  375.                     call  get_unsigned ; unsigned for bx 
  376.                     mov   bx, ax 
  377.                     mov   ax, 0   ; blank ax 
  378.                     call  show_regs 
  379.               
  380.                     call  get_signed ; signed for si 
  381.                     mov   si, ax 
  382.               
  383.                     mov   ax, 0   ; blank ax 
  384.  
  385.  
  386.  
  387.  
  388.              The PC Assembler Tutor                                        120
  389.              ______________________
  390.  
  391.                     lea   cx, [bx+si]+100      ; addresses to cx and dx
  392.                     lea   dx, [si+bx-100]
  393.                     call  show_regs_and_wait 
  394.               
  395.                     jmp   lea_loop 
  396.               ; + + + + END CODE ABOVE THIS LINE 
  397.  
  398.              The first part of the program shows that LEA and MOV give the
  399.              same offset address. Then we enter the loop. It gets an unsigned
  400.              number, puts it in BX, gets a signed number, puts it in SI, then
  401.              uses LEA to calculate [bx+si+100] and [bx+si-100]. The plus and
  402.              minus 100 is simply to show you a difference of 200 in the two
  403.              results. BX and SI could also have contained (1) both signed
  404.              numbers or (2) both unsigned numbers. It doesn't make any
  405.              difference. This program has a signed and an unsigned number for
  406.              variety. Of special interest to you shold be when [bx+si] is
  407.              within 100 of 65536 (or 0). One of the results will be > 0 while
  408.              the other result will be < 65536  The address value wraps around
  409.              from 65535 -> 0. Note that with minor alteration, this program
  410.              can be used to look at ANY addressing mode that uses pointers.  
  411.  
  412.              You should make two executable files for this. First:
  413.  
  414.                  link  lea+asmhelp
  415.  
  416.              and the second:
  417.  
  418.                  link asmhelp+lea
  419.  
  420.              Give them different names and run them. Note the offset values
  421.              for:
  422.  
  423.                  lea  ax, variable1
  424.                  mov  bx, offset variable1
  425.  
  426.              With lea+asmhelp you should have an offset of 8 for variable1
  427.              since there are 8 bytes in the array (ax_byte, bx_byte, etc.).
  428.              This array appears before variable1 in the data segment. When you
  429.              link it the other way (asmhelp+lea), all the data for asmhelp.obj
  430.              is in front of your data and the offset should be something
  431.              completely different for variable1.
  432.  
  433.  
  434.  
  435.  
  436.  
  437.  
  438.  
  439.  
  440.  
  441.  
  442.  
  443.  
  444.  
  445.  
  446.  
  447.  
  448.  
  449.  
  450.  
  451.  
  452.              Chapter 11 - Addressing Modes                                 121
  453.              _____________________________
  454.  
  455.                                         SUMMARY
  456.  
  457.              These are the natural (default) segments of all addressing modes:
  458.  
  459.                  (1) DS
  460.  
  461.                       variable + (constant)
  462.                       [bx] + (constant)
  463.                       [si] + (constant)
  464.                       [di] + (constant)
  465.                       [bx+si] + (constant)
  466.                       [bx+di] + (constant)
  467.  
  468.  
  469.                  (2) SS
  470.  
  471.                       [bp] + (constant)
  472.                       [bp+si] + (constant)
  473.                       [bp+di] + (constant)
  474.  
  475.              Where the constant is optional. Segment overrides may be used.
  476.              The segment overrides are:
  477.  
  478.                  SEGMENT OVERRIDE         MACHINE CODE (hex)
  479.                       CS:                      2E
  480.                       DS:                      3E
  481.                       ES:                      26
  482.                       SS:                      36
  483.  
  484.  
  485.              OFFSET
  486.  
  487.              The reserved word 'offset' tells the assembler to calculate the
  488.              offset of the variable from the beginning of the segment.
  489.  
  490.                       mov  ax, offset variable2
  491.  
  492.  
  493.              SEG
  494.  
  495.              The reserved word 'seg' tells the assembler, linker and loader to
  496.              get the segment address of the segment that the variable is in.
  497.  
  498.                       mov  ax, seg variable2
  499.  
  500.              LEA
  501.  
  502.              LEA calculates an address using any of the 8086 addressing modes,
  503.              then puts the address in a register.
  504.  
  505.                       lea  cx, [bp+di+27] 
  506.  
  507.